home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / kermit / b / ckmtio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-30  |  50.7 KB  |  1,814 lines

  1. /* $Id: ckmtio.c,v 1.9 91/12/27 21:48:25 fdc Exp $
  2.  * $Source: /uw/mackermit/RCS/ckmtio.c,v $
  3.  *------------------------------------------------------------------
  4.  * $Log:    ckmtio.c,v $
  5.  * Revision 1.9  91/12/27  21:48:25  fdc
  6.  * Change fatal to macfatal, make all lines 80 chars or less.
  7.  * 
  8.  * Revision 1.8  91/12/15  23:17:55  rick
  9.  * ut9
  10.  * 
  11.  * Revision 1.7  91/10/13  13:43:39  rick
  12.  * UT(7)
  13.  * 
  14.  * Revision 1.6  91/10/01  12:17:06  rick
  15.  * UT(5)
  16.  * 
  17.  * Revision 1.5  91/09/25  12:17:37  rick
  18.  * Command window in TE. Multiple vt100 windows for command window.
  19.  * 
  20.  * Revision 1.4  91/09/12  21:50:54  rick
  21.  * UT(3). Install on watsun
  22.  * 
  23.  * Revision 1.3  1991/09/12  16:43:03  rick
  24.  * Cleanups.
  25.  *
  26.  * Revision 1.2  1991/09/10  22:21:49  rick
  27.  * Update to UTexas(2)
  28.  *
  29.  * Revision 1.1  1991/09/10  19:18:06  rick
  30.  * Initial revision
  31.  *
  32.  *------------------------------------------------------------------
  33.  * $Endlog$
  34.  */
  35.  
  36. /* edit 3/25/87 by Paul Placeway -- don't let the TextEdit buffer get too */
  37. /*  big, because the Mac will crash if it does */
  38. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  39. /* Ported to Megamax native Macintosh C compiler. */
  40.  
  41. /*  C K M T I O  --  interrupt, console, and port functions for Mac Kermit  */
  42.  
  43. /*
  44.   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
  45.   York.  Permission is granted to any individual or institution to use this
  46.   software as long as it is not sold for profit.  This copyright notice must be
  47.   retained.  This software may not be included in commercial products without
  48.   written permission of Columbia University.
  49. */
  50.  
  51. /*
  52.  Variables:
  53.  
  54.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  55.    dfloc  -- 0 if dftty is console, 1 if external line.
  56.    dfprty -- Default parity
  57.    dfflow -- Default flow control
  58.    ckxech -- Flag for who echoes console typein:
  59.      1 - The program (system echo is turned off)
  60.      0 - The system (or front end, or terminal).
  61.    functions that want to do their own echoing should check this flag
  62.    before doing so.
  63.  
  64.  Functions for assigned communication line (either external or console tty):
  65.  
  66.    ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
  67.    ttclos()                -- Close & reset the tty, releasing any access lock.
  68.    ttpkt(speed,flow)       -- Put the tty in packet mode and set the speed.
  69.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  70.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  71.    ttinc(timo)             -- Timed read character from tty.
  72.    ttchk()                 -- See how many characters in tty input buffer.
  73.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  74.    ttol(string,length)     -- Write a string to the tty.
  75.    ttoc(c)                 -- Write a character to the tty.
  76.    ttflui()                -- Flush tty input buffer.
  77.  
  78. Functions for console terminal:
  79.  
  80.    congm()   -- Get console terminal modes.
  81.    concb()   -- Put the console in single-character wakeup mode with no echo.
  82.    conbin()  -- Put the console in binary (raw) mode.
  83.    conres()  -- Restore the console to mode obtained by congm().
  84.    conoc(c)  -- Unbuffered output, one character to console.
  85.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  86.    conxo(n,s) -- Unbuffered output, n characters to the console.
  87.    conchk()  -- Check if characters available at console.
  88.    coninc()  -- Get a character from the console.
  89.    conint()  -- Enable terminal interrupts on the console.
  90.    connoi()  -- Disable terminal interrupts on the console.
  91.  
  92. Time functions
  93.  
  94.    msleep(m) -- Millisecond sleep
  95.    ztime(&s) -- Return pointer to date/time string
  96. */
  97.  
  98. #include <StdArg.h>
  99.  
  100. #include "ckcdeb.h"        /* Formats for debug() */
  101. #include "ckcker.h"        /* kermit defs */
  102. #include "ckmdef.h"        /* macintosh defs */
  103. #include "ckcasc.h"
  104. #include "ckmwin.h"
  105. #include "ckmcon.h"
  106. #include "ckmptp.h"        /* ckm* Prototypes */
  107.  
  108. char *dftty = "Modem";
  109.  
  110. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  111.  
  112. int dfloc = 1;
  113.  
  114. /* Other defaults */
  115.  
  116. int dfprty = 0;            /* Default parity */
  117. int ttprty = 0;            /* Parity in use. */
  118. long ttspeed = -1;        /* For saving speed */
  119. int dfflow = 1;            /* Xon/Xoff flow control */
  120. int ttflow = -9;        /* For saving flow */
  121. int fDTR = 0;            /* DTR input flow control */
  122. int fCTS = 0;            /* CTS output flow control */
  123. int fInX = 0;            /* send xoff when buffer almost full */
  124.  
  125. int backgrd = 0;        /* a Mac is allways in foreground */
  126.  
  127. /* Local variables */
  128.  
  129. int drop_dtr = 0;        /* drop DTR on Quit */
  130.  
  131. /* buffer and pointer for input processing */
  132. static char *my_input_buf;    /* we give this to the serial driver queue */
  133.  
  134. /* Private buffer for myread() and its companions.  Not for use by anything
  135.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  136.  * allowed to read my_count.
  137.  *
  138.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  139.  *
  140.  * A global parity mask variable could be useful too.  We could use it to
  141.  * let myread() strip the parity on its own, instead of stripping sign
  142.  * bits as it does now.
  143.  */
  144.  
  145. /* #define MYBUFLEN 256 */
  146. #define MYBUFLEN 2048
  147. static unsigned char *mybufp;        /* Buffer, including push back */
  148. static int my_count = 0;        /* Number of chars still in mybuf */
  149. static int my_item = -1;        /* Last index read from mybuf[] */
  150.  
  151.  
  152. #ifdef COMMENT
  153. #define TTBUFL 200        /* good size (it's RBUFL guys!) */
  154. static unsigned char *ttbuf;
  155. #endif
  156.  
  157. static char *tto_buf;    /* output buffer for ttol() */
  158. static ParamBlockRec iopb;    /* paramater block for ttol() */
  159. static long tto_startticks;    /* when we started the output */
  160. #define XOFFTIMEO 480L        /* a timeout of 8 seconds (in ticks) */
  161.  
  162. short dfltVol;        /* The volume to be used for Take- and Log-File */
  163.  
  164. /* true if using RAM serial driver (usually TRUE) */
  165. extern Boolean usingRAMdriver, 
  166.   have_128roms;            /* true if we are a Plus or better */
  167. extern char ttname[];
  168.  
  169. #define SIGTYP long
  170. extern  SIGTYP (*alarmfunc)();
  171. extern  SIGTYP (*intfunc)();
  172. typedef unsigned long ulong;
  173. extern ulong alarmtime = 0;    /* global alarm time */
  174.  
  175. /****************************************************************************/
  176. /*  S Y S I N I T  --  System-dependent program initialization.  */
  177. /****************************************************************************/
  178. sysinit ()
  179. {
  180.     ParamBlockRec pb;
  181.     
  182.     mac_init ();        /* Set up the Mac */
  183.  
  184.     /* get the default volume reference number for Take- and Log-Files */
  185.     pb.volumeParam.ioNamePtr = NIL;
  186.     PBGetVol (&pb, FALSE);
  187.     dfltVol = pb.volumeParam.ioVRefNum;
  188.  
  189.     findfinderfiles ();        /* see if file was selected */
  190.  
  191.     mac_post_load_init ();    /* show the terminal window and stuff */
  192.  
  193.     return (0);
  194. }                /* sysinit */
  195.  
  196. /* init terminal I/O buffers */
  197. inittiobufs()
  198. {
  199. #ifdef COMMENT
  200.     if ((ttbuf = (unsigned char *) NewPtr(TTBUFL + 1)) == NIL)
  201.         macfatal("Can't allocate ttbuf", 0);
  202. #endif
  203.     if ((mybufp = (unsigned char *) NewPtr(MYBUFLEN + 4)) == NIL)
  204.         macfatal("Can't allocate mybufp", 0);
  205.     my_count = 0;        /* Number of chars still in mybuf */
  206.     my_item = -1;        /* Last index read from mybuf[] */
  207.  
  208.     if ((tto_buf = (char *) NewPtr(MAXSP)) == NIL)
  209.         macfatal("Can't allocate tto_buf", 0);
  210.     if ((my_input_buf = (char *) NewPtr(MYBUFSIZE)) == NIL)
  211.         macfatal("Can't allocate my_input_buf", 0);
  212. }
  213.  
  214. /****************************************************************************/
  215. /* P O R T _ O P E N -- Open and init a serial port.  port is either -6 (for */
  216. /*  the modem port) or -8 (for the printer port)                */
  217. /****************************************************************************/
  218.  
  219. #define RamSDOpen RAMSDOPEN        /* fix routine name */
  220.  
  221. port_open (int port)
  222. {
  223.     int err;
  224.         
  225.     if ((port != -6) && (port != -8))
  226.     port = -6;
  227.  
  228. try_again:
  229.     /* Set up IO drivers */
  230.     innum = port;
  231.     outnum = port - 1;
  232.     if (innum == -6) {
  233.     if (((err = OpenDriver ("\p.AIn", &innum)) != noErr) ||
  234.         ((err = OpenDriver ("\p.AOut", &outnum)) != noErr))
  235.         macfatal ("Could not open the Modem port: ", err);
  236.     } else {
  237.     if (((err = OpenDriver ("\p.BIn", &innum)) != noErr) ||
  238.         ((err = OpenDriver ("\p.BOut", &outnum)) != noErr)) {
  239.         printerr("Could not open the Printer port.  Try\
  240.  turning off Appletalk.", 0);
  241.         port = -6;
  242.         goto try_again;
  243.     }
  244.     }
  245.     
  246.     /* try for the RAM driver */
  247.     if (innum == -6)
  248.     err = RamSDOpen (sPortA);
  249.     else
  250.     err = RamSDOpen (sPortB);
  251.     
  252.     if (err == noErr) {
  253.     usingRAMdriver = TRUE;
  254.     } else {
  255.     usingRAMdriver = FALSE;
  256.     printerr("Can't open RAM serial driver; using the ROM driver\
  257.  (without flow control).",0);
  258.     }
  259.  
  260.     err = SerSetBuf (innum, my_input_buf, MYBUFSIZE);
  261.             /* Make driver use larger buff */
  262.     if (err)
  263.     printerr ("Trouble making IO buffer:", err);
  264.  
  265.     switch (port) {
  266.     case -6:
  267.     strcpy(ttname, "Modem");
  268.     break;
  269.     case -8:
  270.     strcpy(ttname, "Printer");
  271.     break;
  272.     }
  273. }
  274.  
  275. /*****************************************************************************/
  276. /* P O R T _ C L O S E -- Close down the serial port.                 */
  277. /*****************************************************************************/
  278.  
  279. #define RamSDClose RAMSDCLOSE
  280.  
  281. port_close()
  282. {
  283.     int err;
  284.     ParamBlockRec cpb;
  285.     
  286.     err = KillIO(innum);    /* Kill off IO drivers */
  287.     if (err != noErr)
  288.         printerr("trouble KillIO-ing serial input driver:",err);
  289.     err = KillIO(outnum);    /* Kill off IO drivers */
  290.     if (err != noErr)
  291.         printerr("trouble KillIO-ing serial output driver:",err);
  292.  
  293.     err = SerSetBuf (innum, NULL, 0);    /* Make driver default buffer */
  294.     if (err != noErr)
  295.         printerr("trouble resetting serial IO buffer:",err);
  296.  
  297.     if (usingRAMdriver) {
  298.     if (!drop_dtr) {
  299.         bzero((char *) &cpb, sizeof(cpb));
  300.         cpb.cntrlParam.ioNamePtr = NULL;    /* IM-IV p226 */
  301.         /* tell the ram driver not to lower DTR on close */
  302.         cpb.cntrlParam.csCode = 16;        /* misc serial control */
  303.         *((unsigned char *) cpb.cntrlParam.csParam) = 0x80;
  304.                 /* don't lower DTR */
  305.         cpb.cntrlParam.ioCRefNum = innum;
  306.         err = PBControl(&cpb, FALSE);
  307.         if ((err != noErr) && (err != -1))
  308.         printerr(
  309.           "trouble telling RAM serial driver (in) not to lower DTR:",
  310.              err);
  311.  
  312.         bzero((char *) &cpb, sizeof(cpb));
  313.         cpb.cntrlParam.ioNamePtr = NULL;    /* IM-IV p226 */
  314.         cpb.cntrlParam.csCode = 16;        /* misc serial control */
  315.         /* don't lower DTR */
  316.         *((unsigned char *) cpb.cntrlParam.csParam) = 0x80;
  317.         cpb.cntrlParam.ioCRefNum = outnum;
  318.         err = PBControl(&cpb, FALSE);
  319.         if ((err != noErr) && (err != -1))
  320.           printerr("\
  321. trouble telling RAM serial driver (out) not to lower DTR:",err);
  322.     }
  323.     
  324.     RamSDClose (sPortA);    /* this "returns" void */
  325.     }
  326.     
  327.     err = CloseDriver (innum);
  328.     if (err != noErr)
  329.     printerr("trouble closing serial input driver:",err);
  330. /*
  331.  * For some reason or other, doing this close on a 64k ROM machine will cause
  332.  * the mouse to freeze.  Since the input driver is the only one that really
  333.  * matters, we just close it.
  334.  */
  335.     if (have_128roms) {
  336.     err = CloseDriver (outnum);
  337.     if (err != noErr)
  338.         printerr("trouble closing serial output driver:",err);
  339.     }
  340. }
  341.  
  342. /****************************************************************************/
  343. /*  T T O P E N  --  Open a tty for exclusive access.  */
  344. /*  Returns 0 on success, -1 on failure.  */
  345. /****************************************************************************/
  346. ttopen (ttname, lcl, modem, timeo)
  347. char *ttname;
  348. int *lcl;
  349. int modem;
  350. int timeo;
  351. {
  352.     int port, *aport;
  353.     char tmp[100];
  354.  
  355.     my_count = 0;            /* Initialize myread() stuff */
  356.     my_item = -1;
  357.  
  358.     if (*lcl < 0)
  359.     *lcl = 1;        /* always in local mode */
  360.  
  361. #ifdef COMMENT
  362.     if (ttbuf == NIL)
  363.         macfatal("No ttbuf", 0);
  364. #endif
  365.     if (mybufp == NIL)
  366.         macfatal("No mybufp", 0);
  367.     if (tto_buf == NIL)
  368.         macfatal("No tto_buf", 0);
  369.     if (my_input_buf == NIL)
  370.         macfatal("No my_input_buf", 0);
  371.  
  372.     iopb.ioParam.ioResult = 0;        /* no pending output */
  373.     
  374.     iopb.ioParam.ioActCount = 0;    /* for error checking in ttol() */
  375.     iopb.ioParam.ioReqCount = 0;
  376.     
  377.     /*
  378.      * Re-open the port if it has changed.
  379.      */
  380.     strcpy(tmp, ttname);
  381.     lower(tmp);
  382.     if (strcmp(tmp, "printer") == 0)
  383.     port = -8;
  384.     else if (strcmp(tmp, "modem") == 0)
  385.     port = -6;
  386.     else {
  387.     printfalert("Unknown port %s, using Modem", ttname);
  388.     port = -6;
  389.     }
  390.     aport = &port;
  391.     if (port != innum) {        /* if port changed */
  392.     port_close();
  393.     port_open(port);
  394.     if (!setserial (innum, outnum, speed, KPARITY_NONE))
  395.         printfalert("Problem setting port speed");
  396.     (void) sershake(flow);
  397.     }
  398.  
  399.     return (0);
  400. }                /* ttopen */
  401.  
  402.  
  403.  
  404. /****************************************************************************/
  405. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  406. /****************************************************************************/
  407. ttclos ()
  408. {
  409.     my_count = 0;            /* Initialize myread() stuff */
  410.     my_item = -1;
  411.  
  412.     return;
  413. }                /* ttclos */
  414.  
  415. /*
  416.  * sershake
  417.  * Set handshake parameters on serial port.
  418.  */
  419. int sershake (int flow)
  420. {
  421.     int err;
  422.     ParamBlockRec pb;
  423.     SerShk *controlparam;    /* To change serial driver paramaters */
  424.  
  425.     bzero((char *)&pb, sizeof(pb));
  426.     controlparam = (SerShk *) &pb.cntrlParam.csParam;
  427.     /*
  428.      * Old code used to issue controls to in and out sides. IM-IV
  429.      * says to use the output driver.
  430.      */
  431.     pb.cntrlParam.ioCRefNum = outnum;
  432.     if (have_128roms)
  433.     pb.cntrlParam.csCode = 14;    /* SerHShake + DTR */
  434.     else
  435.     pb.cntrlParam.csCode = 10;    /* SerHShake */
  436.  
  437.     if (flow)
  438.     controlparam->fXOn = TRUE;    /* obey flow control */
  439.     else
  440.     controlparam->fXOn = FALSE;    /* ignore flow control */
  441.     controlparam->fCTS = fCTS;        /* output flow control */
  442.     controlparam->xOn = 17;
  443.     controlparam->xOff = 19;
  444.     controlparam->errs = FALSE;
  445.     controlparam->evts = FALSE;
  446.     if (flow && usingRAMdriver && fInX)    /* old ROM driver can't do this */
  447.     controlparam->fInX = TRUE;     /* send flow control when almost full */
  448.     else
  449.     controlparam->fInX = FALSE;
  450.     controlparam->fDTR = fDTR;        /* input flow control */
  451.  
  452.     err = PBControl(&pb, FALSE);
  453.     if (err != noErr) {
  454.     printfalert("sershake: problem setting handshake: %d", err);
  455.     return -1;
  456.     }
  457.  
  458.     return 0;
  459. }
  460.  
  461.  
  462.  
  463. /****************************************************************************/
  464. /*  T T P K T  --  Condition the communication line for packets. */
  465. /*  If called with speed > -1, also set the speed.  */
  466. /*  Returns 0 on success, -1 on failure.  */
  467. /****************************************************************************/
  468. ttpkt (spd, flow, parity)    /* we only care about flow here */
  469. int spd;
  470. int flow;
  471. int parity;
  472. {
  473.     ttprty = parity;                    /* Let other tt functions see these. */
  474.     ttspeed = speed;
  475.     ttflow = flow;            /* Now make this available too. */
  476.  
  477.     fInX = TRUE;
  478.     return(sershake(flow));
  479. }
  480.  
  481.  
  482. /****************************************************************************/
  483. /*  T T V T  --  Condition the communication line for a virtual terminal. */
  484. /*  If called with spd > -1, also set the spd.  */
  485. /*  Returns 0 on success, -1 on failure.  */
  486. /****************************************************************************/
  487. ttvt (spd, flow, parity)    /* all ignoreed */
  488. int spd;
  489. int flow;
  490. int parity;
  491. {
  492.     (void) ttres();
  493.     return (0);
  494. }                /* ttvt */
  495.  
  496.  
  497. /****************************************************************************/
  498. /*  T T F L U I  --  Flush tty input buffer */
  499. /****************************************************************************/
  500. ttflui ()
  501. {
  502.     int err;
  503.  
  504.     my_count = 0;            /* Initialize myread() stuff */
  505.     my_item = -1;
  506.  
  507.     err = KillIO (innum);
  508.     if (err)
  509.     printerr ("Bad input clear", err);
  510.  
  511.     return (0);
  512. }                /* ttflui */
  513.  
  514. ttfluo() {                /* Flush output buffer */
  515.     return(0);                /* (dummy for now) */
  516. }
  517.  
  518. /****************************************************************************/
  519. /*  T T S N D B  --  Send a break */
  520. /****************************************************************************/
  521. ttsndb() {
  522.     long finalticks;
  523.  
  524.     /* delay wants 1/60th units */
  525.  
  526.     SerSetBrk (outnum);        /* start breaking */
  527.     Delay ((long) 15, &finalticks);    /* delay about 250ms */
  528.     SerClrBrk (outnum);        /* stop breaking */
  529. }
  530.  
  531. /****************************************************************************/
  532. /*
  533.  *   Flushio:
  534.  *      Initialize some communications constants, and clear screen and
  535.  *      character buffers. */
  536. /****************************************************************************/
  537. flushio ()
  538. {
  539.     int err;
  540.  
  541.     err = KillIO (innum);
  542.     if (err)
  543.     printerr ("Bad input clear", err);
  544.     err = KillIO (outnum);
  545.     if (err)
  546.     printerr ("Bad ouput clear", err);
  547. }                /* flushio */
  548.  
  549.  
  550.  
  551. /****************************************************************************/
  552. /* sendbreak - sends a break across the communictions line.
  553.  *
  554.  * The argument is in units of approximately 0.05 seconds (or 50
  555.  * milliseconds).  To send a break of duration 250 milliseconds the
  556.  * argument would be 5; a break of duration 3.5 seconds would be (umm,
  557.  * lets see now) 70.
  558.  *
  559.  */
  560. /****************************************************************************/
  561. sendbreak (msunit)
  562. int msunit;
  563. {
  564.     long finalticks;
  565.  
  566. /* delay wants 1/60th units.  We have 3/60 (50 ms.) units, convert */
  567.  
  568.     msunit = msunit * 3;
  569.  
  570.     SerSetBrk (outnum);        /* start breaking */
  571.     Delay ((long) msunit, &finalticks);    /* delay */
  572.     SerClrBrk (outnum);        /* stop breaking */
  573. }                /* sendbreak */
  574.  
  575. /****************************************************************************/
  576. /* toggledtr - Turn DTR off, wait a bit, turn it back on.
  577.  *
  578.  * the argument is in the same units as sendbreak (see above).
  579.  */
  580. /****************************************************************************/
  581. toggle_dtr (msunit)
  582. int msunit;
  583. {
  584.     long finalticks;
  585.     ParamBlockRec pb;
  586.     int err;
  587.  
  588.     if (usingRAMdriver) {
  589.     /* delay wants 1/60th units.  We have 3/60 (50 ms.) units, convert */
  590.  
  591.     msunit = msunit * 3;
  592.  
  593.     pb.cntrlParam.csCode = 18;        /* lower DTR */
  594.     pb.cntrlParam.ioCRefNum = outnum;
  595.     err = PBControl (&pb, FALSE);
  596.     if (err != noErr)
  597.         printerr ("toggle_dtr() trouble lowering DTR: ", err);
  598.  
  599.         Delay ((long) msunit, &finalticks);    /* delay */
  600.  
  601.     pb.cntrlParam.csCode = 17;        /* raise DTR */
  602.     pb.cntrlParam.ioCRefNum = outnum;
  603.     err = PBControl (&pb, FALSE);
  604.     if (err != noErr)
  605.         printerr ("toggle_dtr() trouble raising DTR: ", err);
  606.    }
  607. }                /* sendbreak */
  608.  
  609. /****************************************************************************/
  610. /* do_xon - xon the output port and send an xon (control-Q) character        */
  611. /****************************************************************************/
  612. do_xon ()
  613. {
  614.     ParamBlockRec pb;
  615.     int err;
  616.  
  617.     if (usingRAMdriver) {
  618.     pb.cntrlParam.csCode = 22;        /* clear XOFF for my output */
  619.     pb.cntrlParam.ioCRefNum = outnum;
  620.     err = PBControl (&pb, FALSE);
  621.     if (err != noErr)
  622.         printerr ("do_xon() trouble unblocking output port: ", err);
  623.  
  624.     pb.cntrlParam.csCode = 24;        /* unconditionally send XON */
  625.     pb.cntrlParam.ioCRefNum = outnum;
  626.     err = PBControl (&pb, FALSE);
  627.     if (err != noErr)
  628.         printerr ("do_xon() trouble sending XON: ", err);
  629.    } else {
  630.        OutputChar (ttermw, '\021');    /* XON */
  631.    }
  632. }                /* sendbreak */
  633.  
  634. /****************************************************************************/
  635. /*  T T S S P D  --  Set tty speed */
  636. /****************************************************************************/
  637.  
  638. ttsspd (cps) int cps; {    
  639.     if (setserial (innum, outnum, cps*10, KPARITY_NONE))
  640.     return(0);
  641.     else
  642.     return (-1);
  643. }
  644.  
  645.  
  646. /****************************************************************************/
  647. /*  T T G S P D  --  Set tty speed */
  648. /****************************************************************************/
  649.  
  650. long
  651. ttgspd () {
  652.     if (speed <= 0L)
  653.         printerr("Speed got reset, now == ", (int) speed);
  654.     return (speed);
  655. }
  656.  
  657.  
  658. /* Interrupt Functions */
  659.  
  660. /****************************************************************************/
  661. /* Set up terminal interrupts on console terminal */
  662. /* Set an interrupt trap. */
  663. /****************************************************************************/
  664. VOID conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
  665. {
  666.     return;
  667. }                /* conint */
  668.  
  669.  
  670.  
  671. /****************************************************************************/
  672. /* Reset console terminal interrupts */
  673. /****************************************************************************/
  674. VOID connoi ()
  675. {
  676.     return;
  677. }                /* connoi */
  678.  
  679. /****************************************************************************/
  680. /* writeps - write a pascal string to the serial port.
  681.  *
  682.  */
  683. /****************************************************************************/
  684. writeps (s)
  685. char *s;
  686. {
  687.     long wcnt, w2;
  688.     char *s2;
  689.  
  690.     w2 = wcnt = *s++;        /* get count */
  691.  
  692.     for (s2 = s; w2 > 0; w2--, s2++)    /* add parity */
  693.     *s2 = dopar (*s2);
  694.     
  695.     (void) ttol(s, wcnt);    /* ttol will printerr() if it has a problem */
  696.  
  697.     return;
  698. }                /* writeps */
  699.  
  700. extern Boolean have_multifinder;/* true if running under MF */
  701. extern Boolean in_background;    /* becomes true if running MF and in bg */
  702. extern long mf_sleep_time;    /* number of 60ths between task time */
  703.  
  704. /****************************************************************************/
  705. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  706. /****************************************************************************/
  707. ttol (s, n)
  708. char *s;
  709. int n;
  710. {
  711.     long finalticks;
  712.     int err;
  713.     ParamBlockRec cpb;
  714.  
  715. #ifdef COMMENT
  716.     debug(F101,"ttol n","",n);
  717.     debug(F101," s","",s);
  718.  
  719.     /*
  720.      * the straight-forward way to write out a buffer: synchronously
  721.      */
  722.     finalticks = n;
  723.     err = FSWrite(outnum, &finalticks, s);
  724.     if ((err != noErr) || (finalticks != n)) {
  725.     printerr("ttol FSWrite error: ", err);
  726.     return (-1);
  727.     }
  728.     return (n);
  729. #endif
  730.  
  731.     /*
  732.      * The fancy to write out strings: do async writes, waiting for the
  733.      * previous call to finish first (and possibly unsticking the serial
  734.      * driver)
  735.      */
  736.  
  737.     /* wait for previous call to finish */
  738.     /* while the prev. request is still running */
  739.     while (iopb.ioParam.ioResult == 1) {
  740.     /* if we're running protocol */
  741.     if (have_multifinder && protocmd != 0) {
  742.         miniparser (TRUE);    /* keep mac running */
  743.         finalticks = TickCount ();
  744.     } else {        /* else terminal emulation */
  745.         Delay ((long) 1, &finalticks);    /* wait for a bit */
  746.     }
  747.     /* (PWP) If we have waited too long, unblock the output (keep the
  748.        Mac from freezing up) */
  749.     if ((usingRAMdriver) && (finalticks > (tto_startticks + XOFFTIMEO))) {
  750.         cpb.cntrlParam.csCode = 22;        /* clear XOFF for my output */
  751.         cpb.cntrlParam.ioCRefNum = outnum;
  752.         err = PBControl (&cpb, FALSE);
  753.         if (err != noErr)
  754.         printerr ("ttol() trouble unblocking output port: ", err);
  755.         tto_startticks = TickCount ();    /* get starting time */
  756.     }
  757.     }
  758.     
  759.     /* check for errors in previous call */
  760.     if (iopb.ioParam.ioResult) {
  761.     printerr ("Error in previous PBWrite:", iopb.ioParam.ioResult);
  762.     return (-1);
  763.     }
  764.     if (iopb.ioParam.ioActCount != iopb.ioParam.ioReqCount) {
  765.     printerr ("PBWrite to serial didn't write enough: ",
  766.           iopb.ioParam.ioActCount);
  767.     printerr ("(asked for:)", iopb.ioParam.ioReqCount);
  768.     return (-1);
  769.     }
  770.  
  771.     /* the previous call is now done, so we can load in our new information */
  772.     
  773.     if (n > MAXSP) {        /* MAXSP == sizeof(tto_buf) */
  774.         printerr("ttol asked to write too many chars: ", n);
  775.     return (-1);
  776.     }
  777.     bcopy(s, tto_buf, n);    /* in ckmfio.h if nowhere else */
  778.  
  779.     iopb.ioParam.ioCompletion = NULL;
  780.     iopb.ioParam.ioNamePtr = NULL;
  781.     iopb.ioParam.ioVRefNum = 0;
  782.  
  783.     iopb.ioParam.ioRefNum = outnum;
  784.     iopb.ioParam.ioVersNum = 0;
  785.     iopb.ioParam.ioPermssn = 0;
  786.     iopb.ioParam.ioMisc = NULL;
  787.     iopb.ioParam.ioBuffer = tto_buf;
  788.     iopb.ioParam.ioReqCount = (long) n;
  789.     iopb.ioParam.ioPosMode = 0;
  790.     iopb.ioParam.ioPosOffset = 0;
  791.     
  792.     tto_startticks = TickCount ();    /* get starting time */
  793.  
  794.     PBWrite (&iopb, TRUE);    /* request an async. write */
  795.     if (protocmd != 0)
  796.     miniparser (TRUE);    /* allow other tasks to run */
  797.     return (n);            /* fake a good run */
  798. }                /* ttol */
  799.  
  800.  
  801. /*  T T O C  --  Output a character to the communication line  */
  802.  
  803. /*
  804.  This function should only used for interactive, character-mode operations,
  805.  like terminal connection, script execution, dialer i/o, where the overhead
  806.  of the signals and alarms does not create a bottleneck.
  807. */
  808.  
  809. ttoc(c) char c; {
  810.     char foo[2];
  811.     
  812.     foo[0] = c;
  813.     foo[1] = '\0';
  814.     return (ttol(foo, 1));
  815. }
  816.  
  817. /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
  818.  
  819.  
  820. /* myread() -- Efficient read of one character from communications line.
  821.  *
  822.  * Uses a private buffer to minimize the number of expensive read() system
  823.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  824.  * is then returned.  By reading all available input from the system buffers
  825.  * to the private buffer in one chunk, and then working from this buffer, the
  826.  * number of system calls is reduced in any case where more than one character
  827.  * arrives during the processing of the previous chunk, for instance high
  828.  * baud rates or network type connections where input arrives in packets.
  829.  * If the time needed for a read() system call approaches the time for more
  830.  * than one character to arrive, then this mechanism automatically compensates
  831.  * for that by performing bigger read()s less frequently.  If the system load
  832.  * is high, the same mechanism compensates for that too.
  833.  *
  834.  * myread() is a macro that returns the next character from the buffer.  If the
  835.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  836.  * returns.
  837.  *
  838.  * This should be efficient enough for any one-character-at-a-time loops.
  839.  * For even better efficiency you might use memcpy()/bcopy() or such between
  840.  * buffers (since they are often better optimized for copying), but it may not
  841.  * be worth it if you have to take an extra pass over the buffer to strip
  842.  * parity and check for CTRL-C anyway.
  843.  *
  844.  * Note that if you have been using myread() from another program module, you
  845.  * may have some trouble accessing this macro version and the private variables
  846.  * it uses.  In that case, just add a function in this module, that invokes the
  847.  * macro.
  848.  */
  849.  
  850. #define mac_myread(timeo_ticks,intim)  (--my_count < 0 \
  851.             ? mac_mygetbuf(timeo_ticks,intim) \
  852.             : (int) (mybufp[++my_item]))
  853.  
  854. /* Specification: Push back up to one character onto myread()'s queue.
  855.  *
  856.  * This implementation: Push back characters into mybuf. At least one character
  857.  * must have been read through myread() before myunrd() may be used.  After
  858.  * EOF or read error, again, myunrd() can not be used.  Sometimes more than
  859.  * one character can be pushed back, but only one character is guaranteed.
  860.  * Since a previous myread() must have read its character out of mybuf[],
  861.  * that guarantees that there is space for at least one character.  If push
  862.  * back was really needed after EOF, a small addition could provide that.
  863.  *
  864.  * myunrd() is currently not called from anywhere inside kermit...
  865.  */
  866. #ifdef NOTUSED
  867. myunrd(ch) CHAR ch; {
  868.     if (my_item >= 0) {
  869.     mybufp[my_item--] = ch;
  870.     ++my_count;
  871.     }
  872. }
  873. #endif
  874.  
  875. /* mygetbuf() -- Fill buffer for myread() and return first character.
  876.  *
  877.  * This function is what myread() uses when it can't get the next character
  878.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  879.  * to read at least one new character into the buffer, and then it returns
  880.  * the first character just as myread() would have done.  This function also
  881.  * is responsible for all error conditions that myread() can indicate.
  882.  *
  883.  * Returns: When OK    => a positive character, 0 or greater.
  884.  *        When EOF    => -2.
  885.  *        When error    => -3, error code in errno.
  886.  *
  887.  * Older myread()s additionally returned -1 to indicate that there was nothing
  888.  * to read, upon which the caller would call myread() again until it got
  889.  * something.  The new myread()/mygetbuf() always gets something.  If it 
  890.  * doesn't, then make it do so!  Any program that actually depends on the old
  891.  * behaviour will break.
  892.  *
  893.  * The older version also used to return -2 both for EOF and other errors,
  894.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  895.  * other errors now return different results, although Kermit currently never
  896.  * checks to see which it was.  It just disconnects in both cases.
  897.  *
  898.  * Kermit lets the user use the quit key to perform some special commands
  899.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  900.  * finish without reading anything and return the EINTR error.  This should
  901.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  902.  * but if there is nothing to read, this could delay Kermit's reaction to
  903.  * the command, and make Kermit appear unresponsive.
  904.  *
  905.  * The debug() call should be removed for optimum performance.
  906.  */
  907. /* myfillbuf():
  908.  * System-dependent read() into mybuf[], as many characters as possible.
  909.  *
  910.  * Returns: OK => number of characters read, always more than zero.
  911.  *          EOF => 0
  912.  *          Error => -1, error code in errno.
  913.  *
  914.  * If there is input available in the system's buffers, all of it should be
  915.  * read into mybuf[] and the function return immediately.  If no input is
  916.  * available, it should wait for a character to arrive, and return with that
  917.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  918.  * character, but be aware that any such delay lengthens the packet turnaround
  919.  * time during kermit file transfers.  Should never return with zero characters
  920.  * unless EOF or irrecoverable read error.
  921.  *
  922.  * Correct functioning depends on the correct tty parameters being used.
  923.  * Better control of current parameters is required than may have been the
  924.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can 
  925.  * no longer be sometimes off and sometimes on like it used to, unless a 
  926.  * special myfillbuf() is written to handle that.  Otherwise the ordinary 
  927.  * myfillbuf()s may think they have come to EOF.
  928.  *
  929.  * If your system has a facility to directly perform the functioning of
  930.  * myfillbuf(), then use it.  If the system can tell you how many characters
  931.  * are available in its buffers, then read that amount (but not less than 1).
  932.  * If the system can return a special indication when you try to read without
  933.  * anything to read, while allowing you to read all there is when there is
  934.  * something, you may loop until there is something to read, but probably that
  935.  * is not good for the system load.
  936.  */
  937.  
  938.  
  939. mac_mygetbuf(long timeo_tics, long intim) {
  940.     long avail;        /* can't be register */
  941.     long finaltics;    /* can't be register */
  942.     int err;
  943.     extern int tlevel;
  944.     
  945.     if (mybufp == NIL)
  946.         macfatal("No mybufp (in mac_mygetbuf())", 0);
  947.  
  948.     for (;;) {
  949.     SerGetBuf (innum, &avail);    /* Get available count */
  950.  
  951.     if (avail > 0)
  952.         break;            /* we can get these chars */
  953.     
  954.     /* no chars availiable yet */
  955.     if ((protocmd != 0) || (tlevel > -1) || intfunc) {
  956.         miniparser (TRUE);        /* keep mac running */
  957.         if (sstate == 'a')    {    /* abort occured? */
  958.         if (intfunc) {
  959.             sstate = '\0';
  960.             (*intfunc)(0);
  961.         } else
  962.             return (-1);    /* ugh, look like timeout */
  963.         }
  964.     }
  965.         
  966.     /*
  967.      * Check alarm() timeouts.
  968.      */
  969.     if (alarmtime && alarmfunc && (((ulong)TickCount() - alarmtime) > 0))
  970.         (*alarmfunc)(0);
  971.  
  972.     finaltics = TickCount ();
  973.     if (timeo_tics > 0) {        /* Want to do timeout? */
  974.         if (intim + timeo_tics < finaltics) {
  975.         return (-1);    /* Too long, give up */
  976.         }
  977.     }
  978.     
  979.     /* go back and try to get more chars */
  980.     }
  981.  
  982.     if (avail > MYBUFLEN)
  983.     avail = MYBUFLEN;
  984.  
  985.     /*
  986.      * CAREFUL: the Mac FSRead() function gets how much to read,
  987.      * AND PUTS HOW MUCH IT DID READ into avail
  988.      */
  989.     err = FSRead (innum, &avail, mybufp);        /* Into our buffer */
  990.  
  991.     if (err != noErr) {
  992.     screen(SCR_EM,0,(long) err,"Serial input error:");
  993.     return (-3);    /* return input error */
  994.     }
  995.     if (avail <= 0) {
  996.     screen(SCR_EM, 0, (long) avail,
  997.            "No serial input error, but didn't read any:");
  998.     return (-3);    /* return input error */
  999.     }
  1000.  
  1001.     /* not at end of packet yet, so let other tasks have a chance */
  1002.     if (in_background)
  1003.     miniparser (TRUE);    /* allow other tasks to run */
  1004.  
  1005.     my_count = (int) avail;
  1006.     
  1007.     /* debug(F101, "myfillbuf read", "", my_count); */
  1008.  
  1009.     --my_count;
  1010.     return((int) (mybufp[my_item = 0]));
  1011. }
  1012.  
  1013.  
  1014.  
  1015.  
  1016. /****************************************************************************/
  1017. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  1018. /*
  1019.   If no break character encountered within "max", return "max" characters,
  1020.   with disposition of any remaining characters undefined.  Otherwise, return
  1021.   the characters that were read, including the break character, in "dest" and
  1022.   the number of characters read as the value of function, or 0 upon end of
  1023.   file, or -1 if an error occurred.  Times out & returns error if not completed
  1024.   within "timo" seconds.
  1025. */
  1026. /*
  1027.   Reads up to "max" characters from the communication line, terminating on
  1028.   the packet-end character (eol), or timing out and returning -1 if the eol
  1029.   character not encountered within "timo" seconds.  The characters that were
  1030.   input are copied into "dest" with their parity bits stripped if parity was
  1031.   selected.  Returns the number of characters read.  Characters after the
  1032.   eol are available upon the next call to this function.
  1033.  
  1034.   The idea is to minimize the number of system calls per packet, and also to
  1035.   minimize timeouts.  This function is the inner loop of the program and must
  1036.   be as efficient as possible.  The current strategy is to use myread().
  1037.  
  1038.   WARNING: this function calls parchk(), which is defined in another module.
  1039.   Normally, ckutio.c does not depend on code from any other module, but there
  1040.   is an exception in this case because all the other ck?tio.c modules also
  1041.   need to call parchk(), so it's better to have it defined in a common place.
  1042. */
  1043. /****************************************************************************/
  1044.  
  1045. #define CTRLC '\03'
  1046.  
  1047. #ifdef PARSENSE
  1048. ttinl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start; {
  1049.     int flag;
  1050. #else
  1051. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; {
  1052. #endif
  1053.     register int i, m, n;        /* local variables */
  1054.     int x, ccn;
  1055.     long timeoticks;
  1056.     long intim;            /* when we started */
  1057.     
  1058.     debug(F101,"ttinl max","",max);
  1059.     debug(F101,"ttinl timo","",timo);
  1060.  
  1061. #ifdef PARSENSE
  1062.     debug(F000,"ttinl start","",start);
  1063.     flag = 0;                /* Start of packet flag */
  1064. #endif
  1065.  
  1066.     ccn = 0;                /* Control-C counter */
  1067.     x = 0;                /* Return code */
  1068.     m = (ttprty) ? 0177 : 0377;         /* Parity stripping mask. */
  1069.     *dest = '\0';                       /* Clear destination buffer */
  1070.  
  1071.     if (timo <= 0) {        /* untimed */
  1072.     timo = 0;        /* Safety */
  1073.     intim = 0;        /* tell mac_myread not to timeout */
  1074.     timeoticks = 0;
  1075.     } else {
  1076.     timeoticks = timo * 60;
  1077.     intim = TickCount ();    /* now */
  1078.     }
  1079.  
  1080.     i = 0;
  1081.     while (i < max-1) {
  1082.     /* debug(F101,"ttinl i","",i); */
  1083.     if ((n = mac_myread(timeoticks,intim)) < 0) {
  1084.         debug(F101,"ttinl myread failure, n","",n);
  1085.         x = -1; break;
  1086.     }
  1087.     /* debug(F101,"ttinl char","",n&m); */
  1088.  
  1089. #ifdef PARSENSE
  1090.     if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
  1091.     if (flag) dest[i++] = n & m;
  1092. #else
  1093.     dest[i++] = n & m;
  1094. #endif
  1095.     if ((n & 0x7f) == CTRLC) {    /* Check for ^C^C */
  1096.         if (++ccn > 1) {    /* If we got 2 in a row, bail out. */
  1097.             screen(SCR_EM,0,(long) 0,"Remote side ^C^C abort...");
  1098.         return(-2);
  1099.         }
  1100.     } else ccn = 0;        /* Not ^C, so reset ^C counter, */
  1101.  
  1102. #ifdef PARSENSE
  1103.     if (flag == 0) {
  1104.         debug(F101,"ttinl skipping","",n);
  1105.         continue;
  1106.     }
  1107. #endif
  1108.  
  1109.     /* Check for end of packet */
  1110.  
  1111.     if ((n & 0x7f) == eol) {
  1112.         debug(F101,"ttinl got eol","",eol);
  1113.         dest[i] = '\0';        /* Yes, terminate the string, */
  1114.         /* debug(F101,"ttinl i","",i); */
  1115.         
  1116. #ifdef PARSENSE
  1117. /* Here's where we actually check and adjust the parity. */
  1118. /* The major flaw here is if parity is NONE (ttprty = 0) and the packets */
  1119. /* really do have no parity, then parchk() is called for every packet. */
  1120. /* In practice, this doesn't really harm efficiency noticably, but it would */
  1121. /* be better if ttinl() had a way of knowing to stop doing this once a */
  1122. /* particular file transfer had been started and checked. */
  1123.         if (ttprty == 0) {
  1124.         if ((ttprty = parchk(dest,start,i)) > 0) {
  1125.             register int j;
  1126.             debug(F101,"ttinl senses parity","",ttprty);
  1127.             debug(F110,"ttinl packet before",dest,0);
  1128.             for (j = 0; j < i; j++)
  1129.             dest[j] &= 0x7f; /* Strip parity from packet */
  1130.             debug(F110,"ttinl packet after ",dest,0);
  1131.         } else debug(F101,"parchk","",ttprty);
  1132.         }
  1133. #endif
  1134.         debug(F111,"ttinl got", dest,i);
  1135.         return(i);
  1136.     }
  1137.     }        /* end while (i < max-1) */
  1138.     debug(F100,"ttinl timout","",0);    /* Get here on timeout. */
  1139.     debug(F111," with",dest,i);
  1140.     return(x);                          /* and return error code. */
  1141.  
  1142. }                /* ttinl */
  1143.  
  1144.  
  1145. /****************************************************************************/
  1146. /* ttinc(timo) - read a character with timeout.  Return -1 on timeout. */
  1147. /****************************************************************************/
  1148. ttinc (timo)
  1149. int timo;
  1150. {
  1151.     register int m, n = 0;
  1152.     long timeoticks;
  1153.     long intim;            /* when we started */
  1154.  
  1155.     if (timo <= 0) {        /* untimed */
  1156.     intim = 0;        /* tell mac_myread not to timeout */
  1157.     timeoticks = 0;
  1158.     } else {
  1159.     timeoticks = timo * 60;
  1160.     intim = TickCount ();    /* now */
  1161.     }
  1162.     
  1163.     m = (ttprty) ? 0177 : 0377;         /* Parity stripping mask. */
  1164.  
  1165.         /* comm line failure returns -1 thru myread, so no &= 0377 */
  1166.     n = mac_myread(timeoticks,intim);        /* Wait for a character... */
  1167.  
  1168.     /* debug(F101,"ttinc n","",n); */
  1169.     return(n < 0 ? n : n & m);
  1170. }                /* ttinc */
  1171.  
  1172. /****************************************************************************/
  1173. /* PWP: input as many chars as we can read from the serial line right now   */
  1174. /****************************************************************************/
  1175.  
  1176. ttinm(buf, max)
  1177. register char *buf;
  1178. register int max;
  1179. {
  1180.     long avil, num;
  1181.     int err, i;
  1182.  
  1183.     /*
  1184.      * DANGER WILL ROBINSON: this KNOWS about how mac_myread works
  1185.      * (in an insestious way), so BE CAREFUL!!!
  1186.      */
  1187.  
  1188.     if (my_count > 0) {        /* do we have chars buffered up? */
  1189.         for (i = 0; (my_count > 0) && (i < max); i++)
  1190. #ifdef notdef
  1191.         *buf++ = mac_mygetbuf(0L,0L);
  1192. #else
  1193.         *buf++ = mac_myread(0L, 0L);
  1194. #endif
  1195.     return (i);        /* return contents of previous read buffer */
  1196.     }
  1197.  
  1198.     SerGetBuf (innum, &avil);    /* Get available count */
  1199.  
  1200.     if (avil > 0) {    /* Have something? */
  1201.     num = (avil > max) ? max : avil;    /* Set max */
  1202.  
  1203.     err = FSRead (innum, &num, buf);    /* Into our buffer */
  1204.     if (err != noErr)
  1205.         printerr ("Serial input error: ", err);
  1206.     return (num);        /* return how many */
  1207.     } else {
  1208.         return (0);
  1209.     }
  1210. }
  1211.  
  1212. /****************************************************************************/
  1213. /****************************************************************************/
  1214. ttchk ()
  1215. {
  1216.     long avcnt;            /* pascal long */
  1217.  
  1218.     SerGetBuf (innum, &avcnt);    /* get available */
  1219.  
  1220.     return (avcnt + my_count);    /* return avail plus our own */
  1221. }                /* ttchk */
  1222.  
  1223.  
  1224.  
  1225. /****************************************************************************/
  1226. /* T T R E S -- Reset the serial line after doing a protocol things        */
  1227. /****************************************************************************/
  1228. ttres ()
  1229. {
  1230.     fInX = FALSE;
  1231.     return(sershake(flow));
  1232. }
  1233.  
  1234.  
  1235. unsigned long starttime;
  1236. Boolean timerRunning = FALSE;
  1237.  
  1238. /****************************************************************************/
  1239. /*  R T I M E R --  Reset elapsed time counter  */
  1240. /****************************************************************************/
  1241. VOID rtimer ()
  1242. {
  1243.     GetDateTime (&starttime);
  1244.     timerRunning = TRUE;
  1245. }                /* rtimer */
  1246.  
  1247.  
  1248.  
  1249. /****************************************************************************/
  1250. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  1251. /****************************************************************************/
  1252. long
  1253. gtimer ()
  1254. {
  1255.     unsigned long secs;
  1256.  
  1257.     if (timerRunning) {
  1258.     GetDateTime (&secs);
  1259.     return (secs - starttime);
  1260.     timerRunning = FALSE;
  1261.     } else
  1262.     return (0);
  1263. }                /* gtimer */
  1264.  
  1265.  
  1266. /****************************************************************************/
  1267. /*  Z T I M E  --  Return date/time string  */
  1268. /****************************************************************************/
  1269. VOID ztime (s)
  1270. char **s;
  1271. {
  1272. #ifdef COMMENT
  1273. /*
  1274.   This is no good.  ztime() MUST return a string in asctime() format.
  1275. */
  1276.     unsigned long secs;
  1277.     char timestr[10];
  1278.     static char dtime[25];
  1279.  
  1280.     GetDateTime (&secs);
  1281.     IUDateString (secs, shortDate, dtime);
  1282.     p2cstr(dtime);
  1283.     IUTimeString (secs, FALSE, timestr);
  1284.     p2cstr(timestr);
  1285.     strcat (dtime, " ");
  1286.     strcat (dtime, timestr);
  1287.     *s = dtime;
  1288. #else
  1289. #include <Time.h>
  1290.     time_t time(time_t *timer);
  1291.     char *ctime(const time_t *timer);
  1292.     time_t time_now;
  1293.     time_now = time( (time_t) 0 );
  1294.     *s = ctime( &time_now );
  1295. #endif /* COMMENT */
  1296. }                /* ztime */
  1297.  
  1298. /* Console IO routines.  The console is implemented as a text edit structure.
  1299.  * These routines are supported:
  1300.  *
  1301.  * conoc(c)   -- output one character to TE record at insertion point
  1302.  * conol(s)   -- output null terminated string to TE record " "
  1303.  * conoll(s)  -- same but with CR on the end
  1304.  * conxo(n,s) -- n character to TE record " "
  1305.  *
  1306.  */
  1307.  
  1308. #define NILTE ((TEHandle ) NILPTR)
  1309. #define LF 012
  1310. #define CR 015
  1311.  
  1312. /****************************************************************************/
  1313. /*  C O N X O  --  Output string of length len to console text edit record  */
  1314. /****************************************************************************/
  1315. conxo (len, s)
  1316.     int len;
  1317.     register char *s;
  1318. {
  1319.     register char *t;
  1320.     
  1321.     /* change NLs to CRs for the Mac */
  1322.     for (t = s; *t && (t - s < len); t++)
  1323.         if (*t == LF)
  1324.         *t = CR;
  1325.  
  1326.     /* debug (F101, "conxo here: ", s, len); */
  1327.     if (rcmdw->teh == NULL)
  1328.     return(0);
  1329.  
  1330.     TEDeactivate(rcmdw->teh);
  1331.     trimcon(rcmdw, len);
  1332.     TEInsert (s, (long) len, rcmdw->teh);    /* insert the string */
  1333.     TESetSelect(TE_MAX, TE_MAX, rcmdw->teh);
  1334.     TEActivate(rcmdw->teh);
  1335.     rcdwscroll (rcmdw);        /* possibly scroll it */
  1336.  
  1337.     return (0);
  1338. }                /* conxo */
  1339.  
  1340.  
  1341. /****************************************************************************/
  1342. /*  C O N O C  --  Output a character to the console text edit record */
  1343. /****************************************************************************/
  1344. conoc (c)
  1345. char c;
  1346. {
  1347.     (void) conxo (1, &c);
  1348. }                    /* conoc */
  1349.  
  1350.  
  1351.  
  1352. /****************************************************************************/
  1353. /****************************************************************************/
  1354. conopen ()
  1355. {
  1356.     return (1);
  1357. }                                        /* conopen */
  1358.  
  1359.  
  1360.  
  1361. /****************************************************************************/
  1362. /*  C O N O L  --  Write a line to the console text edit record  */
  1363. /****************************************************************************/
  1364. conol (s)
  1365. register char *s;
  1366. {
  1367.     return (conxo (strlen (s), s));
  1368. }                                        /* conol */
  1369.  
  1370.  
  1371.  
  1372.  
  1373. /****************************************************************************/
  1374. /*  C O N O L L  --  Output a string followed by CRLF  */
  1375. /****************************************************************************/
  1376. conoll (s)
  1377. char *s;
  1378. {
  1379.     (void) conol (s);            /* first the string */
  1380.     (void) conoc (CR);            /* now the return */
  1381.     return (0);
  1382. }                /* conoll */
  1383.  
  1384.  
  1385. /*****************************************
  1386.  *    C-Kermit Compatibility routines    *
  1387.  *****************************************/
  1388.  
  1389. /*
  1390.  * dummy routines for MAC
  1391.  */
  1392. #define CINC(v,l)((v+1 == l)? 0 : v+1)
  1393. #define CBL 25                /* console buffer length */
  1394. int cbin = 0;                /* circular buffer pointers */
  1395. int cbout = 0;
  1396. unsigned char cbuf[CBL];        /* console buffer */
  1397.  
  1398. concb (esc)
  1399.     char esc;
  1400. {
  1401. }
  1402.  
  1403. conres ()
  1404. {
  1405. }
  1406.  
  1407. conchk ()
  1408. {
  1409.     if (sstate == 'a')            /* if cmd-. in miniparser */
  1410.     return 1;
  1411.     else
  1412.     return 0;
  1413. }
  1414.  
  1415. tthang ()
  1416. {
  1417.     toggle_dtr(70);
  1418.     return(1);
  1419. }
  1420.  
  1421. VOID setint ()
  1422. {
  1423. }
  1424.  
  1425. int pflag = 1;
  1426.  
  1427. /*
  1428.  * ttgmdm
  1429.  * Get modem control signals.
  1430.  * The mac only has one input handshake (CTS) and one output
  1431.  * line (DTR).  DTR may not be present on older MACS with 
  1432.  * DB-9 (instead of DIN-8) connectors.
  1433.  */
  1434. ttgmdm() 
  1435. {
  1436.     int err, r;
  1437.     SerStaRec stat;
  1438.  
  1439.     err = SerStatus(outnum, &stat);
  1440.     if (err != noErr) {
  1441.     printfalert("ttgmdm: Error getting serial status: %d", err);
  1442.     return -1;            /* not available */
  1443.     }
  1444.     r = 0;
  1445.     if (!stat.ctsHold)
  1446.     r |= BM_CTS;
  1447.     /* 
  1448.      * Always say dtr is on. We may be lying if we've enabled
  1449.      * dtr input flow control.
  1450.      */
  1451.     r |= BM_DTR;
  1452.  
  1453.     return r;
  1454. }
  1455.  
  1456.  
  1457. /*
  1458.  * Things from ckutio.c
  1459.  */
  1460. int ckxech = 1;       /* 0 if system normally echoes console characters, else 1 */
  1461. char *ckxv = "Communications I/O, 5A(080), 14 Jan 92";
  1462. int ttcarr = CAR_AUT;            /* Carrier handling mode. */
  1463.  
  1464. #include "ckuver.h"            /* Version herald */
  1465. char *ckxsys = HERALD;
  1466.  
  1467. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  1468.  *
  1469.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  1470.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  1471.  *  2 = Auto: For "modem direct": The same as "Off".
  1472.  *            For real modem types: Heed carrier during connect, but ignore
  1473.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  1474.  *
  1475.  * As you can see, this setting does not affect dialing, which always ignores
  1476.  * carrier (unless there is some special exception for some modem type).  It
  1477.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  1478.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  1479.  * (or should be) always called before any communications is tried, which
  1480.  * means that, practically speaking, the effect is immediate.
  1481.  *
  1482.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  1483.  *
  1484.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  1485.  * environment (or any non-termio using environment).  Until that time, this
  1486.  * will simply be a no-op for BSD.
  1487.  *
  1488.  * Note that in previous versions, the carrier was most often left unchanged
  1489.  * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT.  This
  1490.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  1491.  * modes.
  1492.  */
  1493. int ttscarr (carrier) 
  1494.     int carrier; 
  1495. {
  1496.     ttcarr = carrier;
  1497.     debug(F101, "ttscarr","",ttcarr);
  1498.     return(ttcarr);
  1499. }
  1500.  
  1501.  
  1502. /*
  1503.  * from ckuusx.c
  1504.  */
  1505. #ifdef DEBUG
  1506. char debfil[50];            /* Debugging log file name */
  1507. #endif /* DEBUG */
  1508. char pktfil[50];            /* Packet log file name */
  1509. #ifdef TLOG
  1510. char trafil[50];            /* Transaction log file name */
  1511. #endif /* TLOG */
  1512. char sesfil[50];            /* Session log file name */
  1513.  
  1514. #include "ckuusr.h"
  1515. char fspec[FSPECL];            /* Filename string for \v(filespec) */
  1516.  
  1517. VOID bgchk () 
  1518. {                                        /* Check background status */
  1519. #ifdef notdef
  1520.     if (bgset < 0) pflag = !backgrd;
  1521.     else pflag = (bgset == 0 ? 1 : 0);
  1522. #endif
  1523. }
  1524.  
  1525. /* 
  1526.  * dbchr() for DEBUG SESSION 
  1527.  */
  1528. char *dbchr (c)
  1529.     int c; 
  1530. {
  1531.     static char s[8];
  1532.     char *cp = s;
  1533.  
  1534.     c &= 0xff;
  1535.     if (c & 0x80) {            /* 8th bit on */
  1536.     sprintf(cp++,"~");
  1537.     c &= 0x7f;
  1538.     }
  1539.     if (c < SP) {            /* Control character */
  1540.     sprintf(cp,"^%c",ctl(c));
  1541.     } else if (c == DEL) {
  1542.     sprintf(cp,"^?");
  1543.     } else {                /* Printing character */
  1544.     sprintf(cp,"%c",c);
  1545.     }
  1546.     cp = s;                /* Return pointer to it */
  1547.     return(cp);
  1548. }
  1549.  
  1550.  
  1551. /*  T T X I N  --  Get n characters from tty input buffer  */
  1552.  
  1553. /*  Returns number of characters actually gotten, or -1 on failure  */
  1554.  
  1555. /*  Intended for use only when it is known that n characters are actually */
  1556. /*  Available in the input buffer.  */
  1557.  
  1558. int ttxin (n,buf) 
  1559.     int n; 
  1560.     CHAR *buf; 
  1561. {
  1562.     int i, c;
  1563.  
  1564.     for (i = 0; i < n; i++) {
  1565.     c = ttinc(0);
  1566.     if (c < 0)
  1567.         return -1;
  1568.     *buf++ = ttinc(0);        /* ignore errors */
  1569.     }
  1570.  
  1571.     return n;
  1572. }
  1573.     
  1574.  
  1575. /*  C O N I N C  --  Get a character from the console  */
  1576.  
  1577. int coninc (timo) 
  1578.     int timo; 
  1579. {
  1580.     int c;
  1581.     
  1582.     newparser(1, 0, (long) timo);    /* wait till timeout, no menus */
  1583.     
  1584.     if (cbin == cbout)            /* if timeout */
  1585.     return -1;
  1586.  
  1587.     c = cbuf[cbout];
  1588.     cbout = CINC(cbout, CBL);        /* advance pointer */
  1589.     
  1590.     return c;
  1591. }
  1592.  
  1593. char *ckxsys = " Apple Macintosh";
  1594.  
  1595. /*
  1596.  * puts for mac console
  1597.  */
  1598. puts (string)
  1599.     char *string;
  1600. {
  1601.     int i;
  1602.  
  1603.     if (cmdinterminal)
  1604.     cursor_erase (ttermw);
  1605.  
  1606.     for (i = 0; i < strlen(string); i++)
  1607.     ucharout(string[i]);
  1608.     
  1609.     if (cmdinterminal) {
  1610.     if (ttermw->scroll_amount) 
  1611.         flushscroll(ctermw);    /* sync the screen */
  1612.     if (ctermw->out_maxcol)        /* KLUDGE */
  1613.         flushbuf(ctermw);        
  1614.     cursor_draw(ctermw);
  1615.     }
  1616. }
  1617.  
  1618.  
  1619. /*
  1620.  * printf for mac console
  1621.  */
  1622. printf (char *format, ...)
  1623. {
  1624.     int i;
  1625.     char string[512];
  1626.     va_list ap;
  1627.  
  1628.     va_start(ap, format);
  1629.     vsprintf(string, format, ap);
  1630.     va_end(ap);
  1631.  
  1632.     if (cmdinterminal)
  1633.     cursor_erase (ttermw);
  1634.  
  1635.     for (i = 0; i < strlen(string); i++)
  1636.     ucharout(string[i]);
  1637.  
  1638.     if (cmdinterminal) {
  1639.     if (ctermw->scroll_amount) 
  1640.         flushscroll(ctermw);        /* sync the screen */
  1641.     if (ctermw->out_maxcol)        /* KLUDGE */
  1642.         flushbuf(ctermw);
  1643.     cursor_draw(ctermw);
  1644.     }
  1645. }
  1646.  
  1647.  
  1648. /*
  1649.  * putchar for mac console
  1650.  */
  1651. putchar (c)
  1652.     char c;
  1653. {
  1654.     if (cmdinterminal)
  1655.     cursor_erase (ttermw);
  1656.  
  1657.     ucharout(c);
  1658.  
  1659.     if (cmdinterminal) {
  1660.     if (ctermw->scroll_amount) 
  1661.         flushscroll(ctermw);        /* sync the screen */
  1662.     if (ctermw->out_maxcol)        /* KLUDGE */
  1663.         flushbuf(ctermw);
  1664.     cursor_draw(ctermw);
  1665.     }
  1666. }
  1667.  
  1668.  
  1669. /*
  1670.  * outchar
  1671.  * output a character to a termw window.
  1672.  */
  1673. void outchar (struct termw *termw, char c)
  1674. {
  1675.     char buf[1];
  1676.  
  1677.     buf[0] = c;
  1678.  
  1679.     printem(termw, buf, 1);
  1680. }
  1681.  
  1682.  
  1683. /*
  1684.  * Send a single character to the console, unix format.
  1685.  * The MPW compiler thinks that '\r' is 0x0a and that
  1686.  * '\n' is 0x0d.  In this routine, we translate things
  1687.  * to the appropriate action.  
  1688.  *
  1689.  * This will be broken if we call this routine with chars
  1690.  * that are already correct, e.g.: CR.
  1691.  */
  1692. ucharout (s)
  1693.     char s;
  1694. {
  1695.     switch (s) {
  1696.     case '\n':                /* unix newline -> CR, LF */
  1697.     cmdout(LF);
  1698.     cmdout(CR);
  1699.     return;
  1700.     case '\r':                /* \r -> CR */
  1701.     cmdout(CR);
  1702.     return;
  1703.     default:
  1704.     cmdout(s);
  1705.     return;
  1706.     }
  1707. }
  1708.  
  1709.  
  1710. /*
  1711.  * cmdout
  1712.  * write a character to the command window
  1713.  * (copied from conxo)
  1714.  */
  1715. VOID cmdout (c)
  1716.     char c;
  1717. {
  1718.     char buf[1];
  1719.  
  1720.     buf[0] = c;
  1721.     /*
  1722.      * Output to terminal window if no command window.
  1723.      */
  1724.     if (cmdinterminal) {
  1725.     printem(ttermw, buf, 1);
  1726.     return;
  1727.     }
  1728.  
  1729.     printem(ctermw, buf, 1);
  1730. }
  1731.  
  1732.  
  1733. /*
  1734.  * getchar for mac console
  1735.  */
  1736. getchar ()
  1737. {
  1738.     int c;
  1739.     
  1740.     while (cbin == cbout) {        /* while buffer is empty */
  1741.     if (sstate = newparser(1, 1, 0L)) {
  1742.         if (sstate == 'p')        /* if wakeup flag */
  1743.         sstate = '\0';
  1744.         else if (sstate == 'n') {    /* if null command state */
  1745.         sstate = '\0';
  1746.         return (-3);
  1747.         } else
  1748.         return(-3);            /* NULL command */
  1749.     }
  1750.     }
  1751.  
  1752.     c = cbuf[cbout];
  1753.     cbout = CINC(cbout, CBL);        /* advance pointer */
  1754.     
  1755.     return c;
  1756. }
  1757.  
  1758.  
  1759. /*
  1760.  * writecbc
  1761.  * Store a character into the console input buffer.
  1762.  */
  1763. writecbc (c)
  1764.     char c;
  1765. {
  1766.     int t;
  1767.  
  1768.     cbuf[cbin] = c;
  1769.     t = CINC(cbin, CBL);        /* advance pointer */
  1770.     if (t == cbout)            /* if buffer was full */
  1771.     return;                /* drop character */
  1772.     cbin = t;
  1773. }
  1774.  
  1775.  
  1776. /*
  1777.  * writecb
  1778.  * Store a pascal string into the console input buffer.
  1779.  */
  1780. writecb (string)
  1781.     char *string;
  1782. {
  1783.     int l, i;
  1784.  
  1785.     l = *string++;            /* length */
  1786.     for (i = 0; i < l; i++)
  1787.     writecbc(*string++);
  1788. }
  1789.  
  1790. /*  C O N B I N  --  Put console in binary mode  */
  1791.  
  1792. /*  Returns 0 if ok, -1 if not  */
  1793.  
  1794. int
  1795. #ifdef CK_ANSIC
  1796. conbin (char esc)
  1797. #else
  1798. conbin (esc) 
  1799.     char esc;
  1800. #endif
  1801. {
  1802.     return 0;
  1803. }
  1804.  
  1805. /*
  1806.  * Junk so Emacs will set local variables to be compatible with Mac/MPW.
  1807.  * Should be at end of file.
  1808.  * this module uses 8 char tabs
  1809.  * 
  1810.  * Local Variables:
  1811.  * tab-width: 8
  1812.  * End:
  1813.  */
  1814.